package com.example.documentsearchengine.searcher;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//索引的入口 处理文件，相当于执行程序
@Slf4j
public class Parser {
    //指定一个加载文档路径
    private static final String INPUT_PATH="D:/Ddoc_searcher_index/jdk-8u461-docs-all/docs/api";
    private Index index=new Index();
//    public void run(){
//        //整个Parser类入口
//        //1.根据上面加载的文件路径，枚举出所有路径(包括其中的子路径)中的html文件
//        long beginTime=System.currentTimeMillis();
//        System.out.println("开始解析");
//        ArrayList<File>list=new ArrayList<>();
//        enumFile(INPUT_PATH,list);
//        long endEnumFileTime=System.currentTimeMillis();
//        System.out.println("遍历文件 消耗时间:"+(endEnumFileTime-beginTime)+"ms");
//       // System.out.println(list.get(0).getName());
//        //2.根据上述文件内容 进行解析并构建索引
//        for(File file:list) {
//            System.out.println("解析"+file.getAbsolutePath());
//            parseHtml(file);
//        }
//        long endparseHtmlTime=System.currentTimeMillis();
//        System.out.println("解析完成 解析文件消耗时间:"+(endparseHtmlTime-endEnumFileTime)+"ms");
//        //3.把内存中构建好的索引数据结构，保存在相对应的文件中
//        index.save();
//        long endTime=System.currentTimeMillis();
//        System.out.println("保存索引完成:"+(endTime-beginTime)+"ms");
//    }
    public void runByThreadPool() throws InterruptedException {
        //整个Parser类入口
        //1.根据上面加载的文件路径，枚举出所有路径(包括其中的子路径)中的html文件
        long beginTime=System.currentTimeMillis();
        System.out.println("开始解析");
        ArrayList<File>fileList=new ArrayList<>();
        enumFile(INPUT_PATH,fileList);
        long endEnumFileTime=System.currentTimeMillis();
        System.out.println("遍历文件 消耗时间:"+(endEnumFileTime-beginTime)+"ms");
        // System.out.println(fileList.get(0).getName());
        CountDownLatch latch=new CountDownLatch(fileList.size());//用于验证fileList遍历完成
        ExecutorService threadPool = Executors.newFixedThreadPool(8);
        //2.根据上述文件内容 进行解析并构建索引
        for(File file:fileList) {
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("解析"+file.getAbsolutePath());
                    parseHtml(file);
                    latch.countDown();
                }
            });
        }
        latch.await();//等待所有文件解析完成
        long endparseHtmlTime=System.currentTimeMillis();
        System.out.println("解析完成 解析文件消耗时间:"+(endparseHtmlTime-endEnumFileTime)+"ms");
        //3.把内存中构建好的索引数据结构，保存在相对应的文件中
        index.save();
        threadPool.shutdown();//手动将线程池中的线程干掉
        long endTime=System.currentTimeMillis();
        System.out.println("保存索引完成:"+(endTime-beginTime)+"ms");
        log.info("保存索引完成:"+(endTime-beginTime)+"ms");
    }

    private void parseHtml(File file){
        //获取相对应的标题
        String title = parseTitle(file);
        //获取Url
        String url = parseUrl(file);
        //转换出正文(需要除去html标签)
        //String content = parseContent(file);
        String content =parseContentByRegex(file);
        //TODO 把解析出来的数据添加到索引数据结构中
        index.addDoc(title,url,content);
    }
    private String parseTitle(File file) {
        String name=file.getName();
        return name.substring(0,name.length()-".html".length());
    }
    private String parseUrl(File file) {
        // 这个 url 是指在线⽂档对应的链接.
        String path1="https://docs.oracle.com/javase/8/docs/api/";
        String path2= file.getAbsolutePath().substring(INPUT_PATH.length());
        return path1+path2;
    }
    private String readFile(File file) {
        try(BufferedReader bufferedReader=new BufferedReader(new FileReader(file))) {
            StringBuilder stringBuilder=new StringBuilder();
            while (true){
                int r=bufferedReader.read();
                if(r==-1){
                    break;
                }
                char read=(char) r;
                if(read=='\n'||read=='\r'){
                    read=' ';
                }
                stringBuilder.append(read);
            }
            return stringBuilder.toString();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    //基于原获取正文基础上优化，将script标签除去
    public String parseContentByRegex(File file){
        //将整个文件读到String中
        String content=readFile(file);
        //替换script内容
        content=content.replaceAll("<srcipt.*?>(.*?)</srcipt>"," ");
        //去除标签
        content=content.replaceAll("<.*?>"," ");
        //合并连续的多个空格
        content=content.replaceAll("\\s+"," ");
        return content;
    }


    public  String parseContent(File file) {
        //读取文件内容,除去html标签和换行
        try {
            BufferedReader bufferedReader =new BufferedReader(new FileReader(file));
            boolean isCopy=true;
            StringBuilder content=new StringBuilder();
            while (true){
                //使用read()方法 预防出现非法字符
                int r = bufferedReader.read();
                if(r==-1){
                    break;
                }
                char read=(char) r;
                if(isCopy){
                if(read=='\n'||read=='\r'){
                    //将换行替换成空格
                    read=' ';
                }
                if(read=='<'){
                    isCopy=false;
                    continue;//避免<添加到正文中
                }
                content.append(read);
                }else {
                    if(read=='>')isCopy=true;
                }
            }
            bufferedReader.close();
            return content.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }



    private void enumFile(String rootPath, List<File> list) {
        File f=new File(rootPath);
        File[]files=f.listFiles();
        for(File file:files){
            if (file.isDirectory()) {
                //通过判断是否为一个目录，最终递归找到所有文件
                enumFile(file.getAbsolutePath(),list);
            }else{
                //排除.html以外的文件
                if(file.getAbsolutePath().endsWith(".html"))
                list.add(file);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //通过main方法来完成索引过程
        Parser parser=new Parser();
        parser.runByThreadPool();
    }
}
